package org.dromara.oce.config;

import io.netty.buffer.ByteBuf;
import lombok.experimental.UtilityClass;

import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.charset.Charset;

/**
 * @desc: 解析Payload结构工具类
 * @author: hhl
 * @date：2025/8/8 10:24
 */
@UtilityClass
public class DeviceUtil {

//    /**
//     * 获取SN长度
//     *
//     * @param byteBuf
//     * @return
//     */
//    public byte getSnLength(ByteBuf byteBuf) {
//        return byteBuf.getByte(0);
//    }
//
//    /**
//     * 获取SN
//     *
//     * @param byteBuf
//     * @return SN内容
//     */
//    public byte[] getSn(ByteBuf byteBuf) {
//        byte[] snBytes = new byte[getSnLength(byteBuf)];
//        // 从byteBuf的第2个字节位置开始读取数据到snBytes数组中
//        byteBuf.getBytes(2, snBytes);
//        return snBytes;
//    }
//
//    /**
//     * 获取时间戳
//     *
//     * @param byteBuf
//     * @return
//     */
//    public int getTimestamp(ByteBuf byteBuf) {
//        /**
//         * 1. 首先调用getSnLength(byteBuf)获取SN长度
//         * 2. 将常量2与SN长度相加，确定读取位置的偏移量
//         */
//        return byteBuf.getInt(2 + getSnLength(byteBuf));
//    }
//
//    /**
//     * 获取JSON字符串
//     *
//     * @param byteBuf
//     * @return
//     */
//    public String getJsonStr(ByteBuf byteBuf) {
//        // 计算JSON数据的起始位置
//        int jsonStartPosition = 2 + getSnLength(byteBuf);
//        // 计算JSON数据的长度
//        int jsonLength = byteBuf.readableBytes() - jsonStartPosition;
//
//        // 读取JSON数据
//        byte[] jsonBytes = new byte[jsonLength];
//        byteBuf.getBytes(jsonStartPosition, jsonBytes);
//        String jsonString = new String(jsonBytes, Charset.forName("UTF-8"));
//        return jsonString;
//    }

    /**
     * 获取消息类型
     *
     * @param byteBuf
     * @return
     */
    public byte getMessageType(ByteBuf byteBuf) {
        // 帧头(2) + 协议主版本号(1) + 协议次版本号(1) = 4字节偏移
        int frameLength = 2 + 1 + 1;
        //消息类型位于第5个字节位置（索引为4）
        return byteBuf.getByte(frameLength);
    }

    /**
     * 获取Payload内容
     *
     * @param byteBuf
     * @return Payload内容
     */
    public byte[] getPayload(ByteBuf byteBuf) {
        // 帧头(2) + 协议主版本号(1) + 协议次版本号(1) + 消息类型(1) + Payload数据长度(2) = 7字节偏移
        int payloadOffset = 2 + 1 + 1 + 1 + 2;

        // 读取Payload长度
        int payloadLength = byteBuf.getShort(2 + 1 + 1 + 1); // 消息类型后2字节是Payload长度

        // 读取Payload内容
        byte[] payload = new byte[payloadLength];
        byteBuf.getBytes(payloadOffset, payload);
        return payload;
    }

    /**
     * 拿取Payload中的SN长度
     *
     * @param payload
     * @return
     */
    public byte getSnLength(byte[] payload) {
        // 读取SN长度（位于Payload的第1个字节）
        return payload[0];
    }

    /**
     * 拿取Payload中的SN（字节）
     *
     * @param payload 结构根据消息类型变化
     * @return sn内容
     */
    public byte[] getSnContent(byte[] payload) {
        // SN长度(1字节)+SN内容（可变长度）
        byte snLength = getSnLength(payload);

        byte[] snBytes = new byte[snLength];
        // 从byteBuf的第2个字节位置开始读取数据到snBytes数组中
        System.arraycopy(payload, 1, snBytes, 0, snLength);
        return snBytes;
    }

    /**
     * 根据起止位置获取内容
     *
     * @param payload
     * @param startIndex
     * @param length
     * @return
     */
    public byte[] getContentByte(byte[] payload, int startIndex, int length) {
        byte[] snBytes = new byte[length];
        System.arraycopy(payload, startIndex, snBytes, 0, length);
        return snBytes;
    }
    
    /**
     * 根据起止位置获取内容
     *
     * @param payload
     * @param startIndex
     * @param length
     * @return
     */
    public short getContentShort(byte[] payload, int startIndex, int length) {
        byte[] snBytes = new byte[length];
        System.arraycopy(payload, startIndex, snBytes, 0, length);
        return ByteBuffer.wrap(snBytes).order(ByteOrder.BIG_ENDIAN).getShort();
    }

    /**
     * 获取SN内容字符串
     *
     * @param snBytes
     * @return
     */
    public String getSnContentStr(byte[] snBytes) {
        String snStr = new String(snBytes, Charset.forName("ASCII"));
        return snStr;
    }

    /**
     * 读取时间戳（位于SN内容之后的4个字节）
     */
    public int getTimestamp(byte[] payload) {
        return ByteBuffer.wrap(payload, 1 + getSnLength(payload), 4).order(ByteOrder.BIG_ENDIAN).getInt();
    }

    /**
     * 构建完整数据帧结构
     *
     * @param messageType 消息类型
     * @param payload     Payload数据
     * @return 完整的数据帧
     */
    public byte[] buildDataFrame(byte messageType, byte[] payload) {
        // 帧头(2) + 协议主版本号(1) + 协议次版本号(1) + 消息类型(1) + Payload数据长度(2) + Payload + 校验(2)
        int frameLength = 2 + 1 + 1 + 1 + 2 + payload.length + 2;
        ByteBuffer frameBuffer = ByteBuffer.allocate(frameLength);
        frameBuffer.order(ByteOrder.BIG_ENDIAN);
        // 帧头 0xAA55
        frameBuffer.putShort((short) 0xAA55);
        // 协议主版本号 (假设为2)
        frameBuffer.put((byte) 0x02);
        // 协议次版本号 (假设为1)
        frameBuffer.put((byte) 0x01);
        // 消息类型
        frameBuffer.put(messageType);
        // 数据长度
        frameBuffer.putShort((short) payload.length);
        // Payload
        frameBuffer.put(payload);

        System.out.println(payload.length);

        // 计算并添加CRC16校验
        // CRC16范围: 消息类型 + 数据长度 + Payload
        byte[] crcData = new byte[1 + 2 + payload.length];
        ByteBuffer.wrap(crcData).put(messageType)
            .putShort((short) payload.length)
            .put(payload);

        int crc16 = calculateCRC16(crcData);
        frameBuffer.putShort((short) crc16);

        return frameBuffer.array();
    }


    /**
     * 计算CRC16校验值
     *
     * @param data 需要计算CRC的数据
     * @return CRC16校验值
     */
    private int calculateCRC16(byte[] data) {
        int crc = 0xFFFF;
        for (byte b : data) {
            crc ^= (b & 0xFF);
            for (int i = 0; i < 8; i++) {
                if ((crc & 0x0001) != 0) {
                    crc >>= 1;
                    crc ^= 0xA001;
                } else {
                    crc >>= 1;
                }
            }
        }
        return crc;
    }


    /**
     * 将字节数组转换为十六进制字符串
     *
     * @param bytes 字节数组
     * @return 十六进制字符串
     */
    public String bytesToHex(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append(String.format("%02X", b));
        }
        return sb.toString();
    }

    /**
     * 将字节数组转换为十进制字符串
     * @param bytes
     * @return
     */
    public static String bytesToDecimalString(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < bytes.length; i++) {
            sb.append(bytes[i] & 0xFF);
            if (i < bytes.length - 1) {
                sb.append(" ");
            }
        }
        return sb.toString();
    }

    /**
     * 将字节数组转换为long
     * @param bytes
     * @return
     */
    public static long bytesToLong(byte[] bytes) {
        // 如果字节数组长度大于8，截取前8字节
        byte[] targetBytes = bytes;
        if (bytes.length > 8) {
            targetBytes = new byte[8];
            System.arraycopy(bytes, 0, targetBytes, 0, 8);
        }

        // 转换为BigInteger再转为long
        BigInteger bi = new BigInteger(1, targetBytes);
        return bi.longValue();
    }



}
